//SPDX-FileCopyrightText: Copyright 2025-2025 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

use proto_gen_rust::board_draw_api::board_draw_api_client::BoardDrawApiClient;
use proto_gen_rust::board_draw_api::*;
use tauri::{AppHandle, Emitter, Runtime};

use super::board_draw_type::NodeContent;
use super::board_draw_type::{decode, encode};
use crate::notice_decode::new_wrong_session_notice;

#[derive(serde::Serialize, serde::Deserialize, Clone, PartialEq, Debug)]
pub struct ExDrawNodeInfo {
    pub node_id: String,
    pub node_style: ::core::option::Option<NodeStyleInfo>,
    pub x: f32,
    pub y: f32,
    pub w: f32,
    pub h: f32,
    pub content: NodeContent,
    pub lock: bool,
    pub create_time: i64,
    pub update_time: i64,
}

#[derive(serde::Serialize, serde::Deserialize, Clone, PartialEq, Debug)]
pub struct ExCreateNodeRequest {
    pub session_id: String,
    pub board_id: String,
    pub draw_id: String,
    pub x: f32,
    pub y: f32,
    pub w: f32,
    pub h: f32,
    pub content: NodeContent,
    pub node_style: NodeStyleInfo,
}

#[derive(serde::Serialize, serde::Deserialize, Clone, PartialEq, Debug)]
pub struct ExUpdateNodeContentRequest {
    pub session_id: String,
    pub board_id: String,
    pub draw_id: String,
    pub node_id: String,
    pub content: NodeContent,
}

#[derive(serde::Serialize, serde::Deserialize, Clone, PartialEq, Debug)]
pub struct ExListNodeResponse {
    pub code: i32,
    pub err_msg: String,
    pub node_list: Vec<ExDrawNodeInfo>,
}

#[derive(serde::Serialize, serde::Deserialize, Clone, PartialEq, Debug)]
pub struct ExGetNodeResponse {
    pub code: i32,
    pub err_msg: String,
    pub node: Option<ExDrawNodeInfo>,
}

#[tauri::command]
pub async fn board_draw_api_cmds_create_draw<R: Runtime>(
    app_handle: AppHandle<R>,
    request: CreateDrawRequest,
) -> Result<CreateDrawResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = BoardDrawApiClient::new(chan.unwrap());
    match client.create_draw(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == create_draw_response::Code::WrongSession as i32 {
                if let Err(err) =
                    &app_handle.emit("notice", new_wrong_session_notice("create_draw".into()))
                {
                    println!("{:?}", err);
                }
            }

            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
pub async fn board_draw_api_cmds_update_draw_basic<R: Runtime>(
    app_handle: AppHandle<R>,
    request: UpdateDrawBasicRequest,
) -> Result<UpdateDrawBasicResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = BoardDrawApiClient::new(chan.unwrap());
    match client.update_draw_basic(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == update_draw_basic_response::Code::WrongSession as i32 {
                if let Err(err) = &app_handle.emit(
                    "notice",
                    new_wrong_session_notice("update_draw_basic".into()),
                ) {
                    println!("{:?}", err);
                }
            }

            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}


#[tauri::command]
pub async fn board_draw_api_cmds_update_draw_edit_member<R: Runtime>(
    app_handle: AppHandle<R>,
    request: UpdateDrawEditMemberRequest,
) -> Result<UpdateDrawEditMemberResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = BoardDrawApiClient::new(chan.unwrap());
    match client.update_draw_edit_member(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == update_draw_edit_member_response::Code::WrongSession as i32 {
                if let Err(err) = &app_handle.emit(
                    "notice",
                    new_wrong_session_notice("update_draw_edit_member".into()),
                ) {
                    println!("{:?}", err);
                }
            }

            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
pub async fn board_draw_api_cmds_remove_draw<R: Runtime>(
    app_handle: AppHandle<R>,
    request: RemoveDrawRequest,
) -> Result<RemoveDrawResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = BoardDrawApiClient::new(chan.unwrap());
    match client.remove_draw(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == remove_draw_response::Code::WrongSession as i32 {
                if let Err(err) =
                    &app_handle.emit("notice", new_wrong_session_notice("remove_draw".into()))
                {
                    println!("{:?}", err);
                }
            }

            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
pub async fn board_draw_api_cmds_list_draw<R: Runtime>(
    app_handle: AppHandle<R>,
    request: ListDrawRequest,
) -> Result<ListDrawResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = BoardDrawApiClient::new(chan.unwrap());
    match client.list_draw(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == list_draw_response::Code::WrongSession as i32 {
                if let Err(err) =
                    &app_handle.emit("notice", new_wrong_session_notice("list_draw".into()))
                {
                    println!("{:?}", err);
                }
            }

            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
pub async fn board_draw_api_cmds_get_draw<R: Runtime>(
    app_handle: AppHandle<R>,
    request: GetDrawRequest,
) -> Result<GetDrawResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = BoardDrawApiClient::new(chan.unwrap());
    match client.get_draw(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == get_draw_response::Code::WrongSession as i32 {
                if let Err(err) =
                    &app_handle.emit("notice", new_wrong_session_notice("get_draw".into()))
                {
                    println!("{:?}", err);
                }
            }

            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
pub async fn board_draw_api_cmds_create_node<R: Runtime>(
    app_handle: AppHandle<R>,
    request: ExCreateNodeRequest,
) -> Result<CreateNodeResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = BoardDrawApiClient::new(chan.unwrap());
    let content = encode(&request.content);
    if content.is_err() {
        return Err(content.err().unwrap().to_string());
    }
    let content = content.unwrap();
    let real_request = CreateNodeRequest {
        session_id: request.session_id,
        board_id: request.board_id,
        draw_id: request.draw_id,
        x: request.x,
        y: request.y,
        w: request.w,
        h: request.h,
        content: Some(content),
        node_style: Some(request.node_style),
    };
    match client.create_node(real_request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == create_node_response::Code::WrongSession as i32 {
                if let Err(err) =
                    &app_handle.emit("notice", new_wrong_session_notice("create_node".into()))
                {
                    println!("{:?}", err);
                }
            }

            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
pub async fn board_draw_api_cmds_update_node_content<R: Runtime>(
    app_handle: AppHandle<R>,
    request: ExUpdateNodeContentRequest,
) -> Result<UpdateNodeContentResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = BoardDrawApiClient::new(chan.unwrap());
    let content = encode(&request.content);
    if content.is_err() {
        return Err(content.err().unwrap().to_string());
    }
    let content = content.unwrap();
    let real_request = UpdateNodeContentRequest {
        session_id: request.session_id,
        board_id: request.board_id,
        draw_id: request.draw_id,
        node_id: request.node_id,
        content: Some(content),
    };
    match client.update_node_content(real_request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == update_node_content_response::Code::WrongSession as i32 {
                if let Err(err) = &app_handle.emit(
                    "notice",
                    new_wrong_session_notice("update_node_content".into()),
                ) {
                    println!("{:?}", err);
                }
            }

            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
pub async fn board_draw_api_cmds_update_node_position<R: Runtime>(
    app_handle: AppHandle<R>,
    request: UpdateNodePositionRequest,
) -> Result<UpdateNodePositionResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = BoardDrawApiClient::new(chan.unwrap());
    match client.update_node_position(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == update_node_position_response::Code::WrongSession as i32 {
                if let Err(err) = &app_handle.emit(
                    "notice",
                    new_wrong_session_notice("update_node_position".into()),
                ) {
                    println!("{:?}", err);
                }
            }

            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
pub async fn board_draw_api_cmds_update_node_style<R: Runtime>(
    app_handle: AppHandle<R>,
    request: UpdateNodeStyleRequest,
) -> Result<UpdateNodeStyleResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = BoardDrawApiClient::new(chan.unwrap());
    match client.update_node_style(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == update_node_style_response::Code::WrongSession as i32 {
                if let Err(err) = &app_handle.emit(
                    "notice",
                    new_wrong_session_notice("update_node_style".into()),
                ) {
                    println!("{:?}", err);
                }
            }

            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
pub async fn board_draw_api_cmds_update_node_size<R: Runtime>(
    app_handle: AppHandle<R>,
    request: UpdateNodeSizeRequest,
) -> Result<UpdateNodeSizeResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = BoardDrawApiClient::new(chan.unwrap());
    match client.update_node_size(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == update_node_size_response::Code::WrongSession as i32 {
                if let Err(err) = &app_handle.emit(
                    "notice",
                    new_wrong_session_notice("update_node_size".into()),
                ) {
                    println!("{:?}", err);
                }
            }

            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
pub async fn board_draw_api_cmds_update_node_lock<R: Runtime>(
    app_handle: AppHandle<R>,
    request: UpdateNodeLockRequest,
) -> Result<UpdateNodeLockResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = BoardDrawApiClient::new(chan.unwrap());
    match client.update_node_lock(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == update_node_lock_response::Code::WrongSession as i32 {
                if let Err(err) = &app_handle.emit(
                    "notice",
                    new_wrong_session_notice("update_node_lock".into()),
                ) {
                    println!("{:?}", err);
                }
            }

            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
pub async fn board_draw_api_cmds_list_node<R: Runtime>(
    app_handle: AppHandle<R>,
    request: ListNodeRequest,
) -> Result<ExListNodeResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = BoardDrawApiClient::new(chan.unwrap());
    match client.list_node(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == list_node_response::Code::WrongSession as i32 {
                if let Err(err) =
                    &app_handle.emit("notice", new_wrong_session_notice("list_node".into()))
                {
                    println!("{:?}", err);
                }
            }
            let mut node_list = Vec::new();
            for node in inner_resp.node_list {
                let content = match &node.content {
                    None => NodeContent::UnkwownContent(
                        proto_gen_rust::board_draw_type::UnkwownContent {},
                    ),
                    Some(real_content) => decode(real_content),
                };
                node_list.push(ExDrawNodeInfo {
                    node_id: node.node_id,
                    node_style: node.node_style,
                    x: node.x,
                    y: node.y,
                    w: node.w,
                    h: node.h,
                    content: content,
                    lock: node.lock,
                    create_time: node.create_time,
                    update_time: node.update_time,
                });
            }

            return Ok(ExListNodeResponse {
                code: inner_resp.code,
                err_msg: inner_resp.err_msg,
                node_list: node_list,
            });
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
pub async fn board_draw_api_cmds_get_node<R: Runtime>(
    app_handle: AppHandle<R>,
    request: GetNodeRequest,
) -> Result<ExGetNodeResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = BoardDrawApiClient::new(chan.unwrap());
    match client.get_node(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == get_node_response::Code::WrongSession as i32 {
                if let Err(err) =
                    &app_handle.emit("notice", new_wrong_session_notice("get_node".into()))
                {
                    println!("{:?}", err);
                }
            }

            if inner_resp.node.is_none() {
                return Ok(ExGetNodeResponse {
                    code: inner_resp.code,
                    err_msg: inner_resp.err_msg,
                    node: None,
                });
            }

            let node = inner_resp.node.unwrap();

            let content = match &node.content {
                None => {
                    NodeContent::UnkwownContent(proto_gen_rust::board_draw_type::UnkwownContent {})
                }
                Some(real_content) => decode(real_content),
            };
            return Ok(ExGetNodeResponse {
                code: inner_resp.code,
                err_msg: inner_resp.err_msg,
                node: Some(ExDrawNodeInfo {
                    node_id: node.node_id,
                    node_style: node.node_style,
                    x: node.x,
                    y: node.y,
                    w: node.w,
                    h: node.h,
                    content: content,
                    lock: node.lock,
                    create_time: node.create_time,
                    update_time: node.update_time,
                }),
            });
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
pub async fn board_draw_api_cmds_remove_node<R: Runtime>(
    app_handle: AppHandle<R>,
    request: RemoveNodeRequest,
) -> Result<RemoveNodeResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = BoardDrawApiClient::new(chan.unwrap());
    match client.remove_node(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == remove_node_response::Code::WrongSession as i32 {
                if let Err(err) =
                    &app_handle.emit("notice", new_wrong_session_notice("remove_node".into()))
                {
                    println!("{:?}", err);
                }
            }

            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}


#[tauri::command]
pub async fn board_draw_api_cmds_create_edge<R: Runtime>(
    app_handle: AppHandle<R>,
    request: CreateEdgeRequest,
) -> Result<CreateEdgeResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = BoardDrawApiClient::new(chan.unwrap());
    match client.create_edge(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == create_edge_response::Code::WrongSession as i32 {
                if let Err(err) =
                    &app_handle.emit("notice", new_wrong_session_notice("create_edge".into()))
                {
                    println!("{:?}", err);
                }
            }

            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
pub async fn board_draw_api_cmds_update_edge_basic<R: Runtime>(
    app_handle: AppHandle<R>,
    request: UpdateEdgeBasicRequest,
) -> Result<UpdateEdgeBasicResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = BoardDrawApiClient::new(chan.unwrap());
    match client.update_edge_basic(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == update_edge_basic_response::Code::WrongSession as i32 {
                if let Err(err) =
                    &app_handle.emit("notice", new_wrong_session_notice("update_edge_basic".into()))
                {
                    println!("{:?}", err);
                }
            }

            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
pub async fn board_draw_api_cmds_list_edge<R: Runtime>(
    app_handle: AppHandle<R>,
    request: ListEdgeRequest,
) -> Result<ListEdgeResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = BoardDrawApiClient::new(chan.unwrap());
    match client.list_edge(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == list_edge_response::Code::WrongSession as i32 {
                if let Err(err) =
                    &app_handle.emit("notice", new_wrong_session_notice("list_edge".into()))
                {
                    println!("{:?}", err);
                }
            }

            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
pub async fn board_draw_api_cmds_get_edge<R: Runtime>(
    app_handle: AppHandle<R>,
    request: GetEdgeRequest,
) -> Result<GetEdgeResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = BoardDrawApiClient::new(chan.unwrap());
    match client.get_edge(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == get_edge_response::Code::WrongSession as i32 {
                if let Err(err) =
                    &app_handle.emit("notice", new_wrong_session_notice("get_edge".into()))
                {
                    println!("{:?}", err);
                }
            }

            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
pub async fn board_draw_api_cmds_remove_edge<R: Runtime>(
    app_handle: AppHandle<R>,
    request: RemoveEdgeRequest,
) -> Result<RemoveEdgeResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = BoardDrawApiClient::new(chan.unwrap());
    match client.remove_edge(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == remove_edge_response::Code::WrongSession as i32 {
                if let Err(err) =
                    &app_handle.emit("notice", new_wrong_session_notice("remove_edge".into()))
                {
                    println!("{:?}", err);
                }
            }

            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
pub async fn board_draw_api_cmds_remove_edge_by_handle<R: Runtime>(
    app_handle: AppHandle<R>,
    request: RemoveEdgeByHandleRequest,
) -> Result<RemoveEdgeByHandleResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = BoardDrawApiClient::new(chan.unwrap());
    match client.remove_edge_by_handle(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == remove_edge_by_handle_response::Code::WrongSession as i32 {
                if let Err(err) =
                    &app_handle.emit("notice", new_wrong_session_notice("remove_edge_by_handle".into()))
                {
                    println!("{:?}", err);
                }
            }

            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
pub async fn board_draw_api_cmds_report_mouse_position<R: Runtime>(
    app_handle: AppHandle<R>,
    request: ReportMousePositionRequest,
) -> Result<ReportMousePositionResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = BoardDrawApiClient::new(chan.unwrap());
    match client.report_mouse_position(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == report_mouse_position_response::Code::WrongSession as i32 {
                if let Err(err) =
                    &app_handle.emit("notice", new_wrong_session_notice("report_mouse_position".into()))
                {
                    println!("{:?}", err);
                }
            }

            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}